<?php
namespace App\Http\Controllers\Api\Egg;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\UserCoinLog;

/**
 * 砸蛋
 *
 * @author  Kay
 * @version 1.0.0
 */
class EggController extends Controller {

    const business_id   = 3;        // 一百万的蛋
    const INCREMENT     = 1;
    const ONE_MILLION   = 1000000;  // 一百万

    protected $wechat;
    protected $result_tips = [
        '锲而舍之，朽木不折；锲而不舍，金石可镂。——荀子',
        '滴水穿石，不是因其力量，而是因其坚韧不拔锲而不舍。——拉蒂默',
        '贵有恒，何必三更起五更眠。最无益，只怕一日曝十日寒。——毛泽东',
        '告诉你使我达到目标的奥秘吧。我唯一的力量就是我的坚持精神。——巴斯德',
    ];

    protected $config = [
        'level_1' => [
            'peilv' => [
                1   => ['id' => 0, 'name' => '赢', 'rate' => 10],
                2   => ['id' => 1, 'name' => '赢', 'rate' => 10],
                3   => ['id' => 2, 'name' => '输', 'rate' => 10],
                4   => ['id' => 3, 'name' => '平', 'rate' => 10],
                5   => ['id' => 4, 'name' => '平', 'rate' => 10],
                6   => ['id' => 5, 'name' => '平', 'rate' => 10],
                7   => ['id' => 6, 'name' => '平', 'rate' => 10],
                8   => ['id' => 7, 'name' => '平', 'rate' => 10],
                9   => ['id' => 8, 'name' => '平', 'rate' => 10],
                10  => ['id' => 9, 'name' => '平', 'rate' => 10],
            ],
        ],
        'level_2' => [
            'peilv' => [
                1   => ['id' => 0, 'name' => '赢', 'rate' => 10],
                2   => ['id' => 1, 'name' => '赢', 'rate' => 10],
                3   => ['id' => 2, 'name' => '输', 'rate' => 10],
                4   => ['id' => 3, 'name' => '平', 'rate' => 10],
                5   => ['id' => 4, 'name' => '平', 'rate' => 10],
                6   => ['id' => 5, 'name' => '平', 'rate' => 10],
                7   => ['id' => 6, 'name' => '平', 'rate' => 10],
                8   => ['id' => 7, 'name' => '平', 'rate' => 10],
                9   => ['id' => 8, 'name' => '平', 'rate' => 10],
                10  => ['id' => 9, 'name' => '平', 'rate' => 10],
            ],
        ],
        'level_3' => [
            'peilv' => [
                1   => ['id' => 0, 'name' => '赢', 'rate' => 10],
                2   => ['id' => 1, 'name' => '赢', 'rate' => 10],
                3   => ['id' => 2, 'name' => '输', 'rate' => 10],
                4   => ['id' => 3, 'name' => '平', 'rate' => 10],
                5   => ['id' => 4, 'name' => '平', 'rate' => 10],
                6   => ['id' => 5, 'name' => '平', 'rate' => 10],
                7   => ['id' => 6, 'name' => '平', 'rate' => 10],
                8   => ['id' => 7, 'name' => '平', 'rate' => 10],
                9   => ['id' => 8, 'name' => '平', 'rate' => 10],
                10  => ['id' => 9, 'name' => '平', 'rate' => 10],
            ],
        ]
    ];

    public function __construct() {
        $this->wechat = app('wechat');
    }

    /**
     * 【游戏页】获取个人信息
     *
     * @return [type] [description]
     */
    public function getUserInfo() {
        $mid = $this->getLoginUser();
        DB::setFetchMode(\PDO::FETCH_ASSOC);
        $user_egg = DB::table('game_egg_user')->where('mid', $mid)->first();
        if (empty($user_egg)) {
            $this->echoJson(1, '您的蛋还没有下出来');
        }

        $redis = $this->getRedis();

        // 获取未持久化数量
        $egg_day_rank   = sprintf('egg-day-rank-%s-%s', date('Ymd'), $mid);
        $egg_week_rank  = sprintf('egg-week-rank-%s-%s', date('W'), $mid);
        $egg_total_rank = sprintf('egg-total-rank-%s', $mid);

        // 更新用户砸蛋数据
        $update = [
            'day_click'     => intval($redis->get($egg_day_rank)),
            'week_click'    => intval($redis->get($egg_week_rank)),
            'total_click'   => intval($redis->get($egg_total_rank)),
        ];
        DB::table('game_egg_user')->where('mid', $mid)->update($update);

        // 判断是否点够一百万次
        if (intval($redis->get($egg_total_rank)) >= self::ONE_MILLION) {
            $user_egg['result'] = $this->result_tips[$mid%4];
        } else {
            $user_egg['result'] = '';
        }

        $user_egg['day_click'] = intval($update['day_click']);
        $user_egg['week_click'] = intval($update['week_click']);
        $user_egg['total_click'] = intval($update['total_click']);

        $user_egg['xyb'] = UserCoinLog::totalXyb($mid) * 100;

        $this->echoJson(0, '', $user_egg);
    }

     /**
     * 【游戏页】点击蛋
     *
     * @return [type] [description]
     */
    function click() {

        // 限定一秒内至多5次点击
        $mid = $this->getLoginUser();

        // 限定操作频次
        $redis = $this->getRedis();
        $key = "egg:limit:click:$mid";
        if (!$redis->set($key, 'Y', Array('nx', 'px' => 50))) {
            $this->echoJson(1, '您的操作过于频繁，请稍后再试');
        }

        // 记录日、周、总点击次数
        $egg_day_rank   = sprintf('egg-day-rank-%s-%s', date('Ymd'), $mid);
        $egg_week_rank  = sprintf('egg-week-rank-%s-%s', date('W'), $mid);
        $egg_total_rank = sprintf('egg-total-rank-%s', $mid);

        // 检验点击满一百万次
        if (intval($redis->get($egg_total_rank)) >= self::ONE_MILLION) {
            $data['result'] = $this->result_tips[$mid%4];
            $this->echoJson(0, '', $data);
        }

        $ret = $redis->multi()
            ->incr($egg_day_rank)
            ->setTimeout($egg_day_rank, 24*60*60)
            ->incr($egg_week_rank)
            ->setTimeout($egg_week_rank, 7*24*60*60)
            ->incr($egg_total_rank)
            ->setTimeout($egg_total_rank, 365*24*60*60)
            ->exec();

        // 数据库写入最小时间隔3秒
        if ($redis->set("egg:persistence:$mid", 'Y', Array('nx', 'px'=>3000))) {
            $update = [
                'day_click'     => intval($ret[0]),
                'week_click'    => intval($ret[2]),
                'total_click'   => intval($ret[4]),
            ];
            $user_egg = DB::table('game_egg_user')->where('mid', $mid)->update($update);
        }
        $ret2 = [];
        foreach($ret as $k => $v) {
            $ret2[$k] = $v;
        }
        $data['ret'] = $ret2;

        // 判断是否点够一百万次
        if (intval($ret[4]) >= self::ONE_MILLION) {
            $data['result'] = $this->result_tips[$mid%4];
        } else {
            $data['result'] = '';
            $data['xyb'] = 0;

            // 限定每秒至多产生一次阳光
            $key = "egg:limit:xyb:$mid";
            if ($redis->set($key, 'Y', ['nx', 'px' => 1000])) {
                DB::setFetchMode(\PDO::FETCH_ASSOC);
                $egg_user = DB::table('game_egg_user')->where('mid', $mid)->first();
                $xyb_upper_limit = $egg_user['xyb_upper_limit'];
                $level = $egg_user['level'];
                $user_xyb = DB::table('user_coin_log')
                    ->where('user_id', $mid)
                    ->where('type', 1)
                    ->where('bussiness_id', self::business_id)
                    ->sum('coin');
                // 不允许超过上限阀值
                if (bccomp($user_xyb, $xyb_upper_limit, 2) === -1) {
                    $peilv = $this->config["level_$level"]['peilv'];
                    $result = $this->get_rand($peilv);
                    if (intval($result) > 0) {
                        $this->updateUserXYB($mid, bcdiv($result, 100, 2));
                        $data['xyb'] = $result;
                    }
                }
            }


        }
        $this->echoJson(0, '', $data);
    }

    /**
     * 抽奖
     * @return [type] [description]
     */
    function lottery() {
        $uid = $this->getLoginUser();

        // 限定操作频次
        $redis = $this->getRedis();
        $key = "egg:limit:lottery:$uid";
        if (!$redis->set($key, 'Y', Array('nx', 'px' => 1000))) {
            $this->echoJson(1, '您的操作过于频繁，请稍后再试');
        }

        // 剩余抽奖次数设置为0
        DB::table('game_egg_user')->where('mid', $uid)->update(['lottery_num' => 0]);

        return $this->echoJson(0, '');
    }

    /**
     * 【游戏页】排行榜
     *
     * @return [type] [description]
     */
    function rank() {

        $mid = $this->getLoginUser();

        // 好友日榜
        $dayList = DB::table('game_egg_user')
        ->join('user', 'user.id', '=', 'game_egg_user.mid')
        ->select('game_egg_user.*')
        ->where('user.finder_id', $mid)
        ->orderBy('day_click', 'desc')
        ->limit(200)
        ->get()
        ->toArray();

        // 好友周榜
        $weekList = DB::table('game_egg_user')
        ->join('user', 'user.id', '=', 'game_egg_user.mid')
        ->select('game_egg_user.*')
        ->where('user.finder_id', $mid)
        ->orderBy('week_click', 'desc')
        ->limit(200)
        ->get()
        ->toArray();

        // 世界日榜
        $globalDayList = DB::table('game_egg_user')
        ->orderBy('day_click', 'desc')
        ->limit(200)
        ->get()
        ->toArray();

        // 世界周榜
        $globalWeekList = DB::table('game_egg_user')
        ->orderBy('week_click', 'desc')
        ->limit(200)
        ->get()
        ->toArray();

        // 响应数据
        $data = [
            'dayList'        => $dayList,
            'weekList'       => $weekList,
            'globalDayList'  => $globalDayList,
            'globalWeekList' => $globalWeekList,
        ];

        $this->echoJson(0, '', $data);
    }

    /**
     * 【游戏页】支付9块银蛋升级金蛋
     *
     * @return [type] [description]
     */
    function upgrade() {
        $mid = $this->getLoginUser();

        $cnt = DB::table('game_egg_user')
            ->join('user', 'user.id', '=', 'game_egg_user.mid')
            ->select('user.id')
            ->where('game_egg_user.level', 2)
            ->where('user.finder_id', 1)
            ->count();

        var_dump($cnt);exit;

        $data = [
            'cnt' => $cnt,
        ];
        $this->echoJson(0, '', $data);

    }

    /**
     * 更新用户小妖币
     *
     * @param  [type] $uid  [description]
     * @param  [type] $gold [description]
     * @return [type]       [description]
     */
    private function updateUserXYB($uid, $gold) {
        $key = sprintf("%s-%s-%s-%s", self::business_id, $uid, $gold, time());
        $tips = '一百万的蛋获得小妖币';
        UserCoinLog::log(self::business_id, $uid, UserCoinLog::TYPE_XYB, $gold, $tips, $key);
    }

    /**
     * 概率算法
     *
     * @param  [type] $rand [description]
     * @return [type]       [description]
     */
    private function get_rand($rand) {
        $result = '';
        //概率数组的总概率精度
        $sum = 0;
        foreach ($rand as $v) {
            $sum += $v['rate'] * 100;
        }
        //概率数组循环
        foreach ($rand as $v) {
            $rate = $v['rate'] * 100;
            //抽取随机数
            $rand_num = mt_rand(1, $sum);
            if ($rand_num <= $rate) {
                //得出结果
                $result = $v['id'];
                break;
            } else {
                $sum -= $rate;
            }
        }
        unset ($rand);
        return $result;
    }

    /**
     * 验证登录
     *
     * @return [type] [description]
     */
    private function getLoginUser() {

        // 检查用户登录态
        $user = auth()->user();
        $mid = $user->id;

        // 初始化用户的银蛋
        $user_egg = DB::table('game_egg_user')->where('mid', $mid)->first();
        if (empty($user_egg)) {
            $data = [
                'mid' => $mid,
                'level' => 1,
                'nickname' => $user->nickname,
                'avatar' => $user->avatar,
                'day_click' => 0,
                'week_click' => 0,
                'total_click' => 0,
            ];
            DB::table('game_egg_user')->insert($data);
        }

        return $mid;
    }

    /**
     * 获取Redis实例
     *
     * @return [type] [description]
     */
    private function getRedis() {
        static $redis = null;
        if (empty($redis)) {
            $redis = new \Redis();
            $redis->connect(env('REDIS_HOST'), env('REDIS_PORT'));
            $redis->auth(env('REDIS_PASSWORD'));
        }
        return $redis;
    }

    /**
     * 响应JSON/JSONP格式数据
     *
     * @param  integer $code [返回代码：0 成功 1 失败]
     * @param  string  $msg  [错误信息]
     * @param  array   $data [返回数据]
     * @return [type]        [description]
     */
    private function echoJson($code = 0, $msg = '', $data = []) {
        header('Content-type: application/json');
        $result = [
            'code'  => $code,
            'msg'   => $msg,
            'data'  => $data,
        ];
        $json = json_encode($result);

        // JSONP
        if (!empty($_GET['callback'])) {
            $json = $_GET['callback'] . "(" . $json . ")";
        }
        echo $json;
        exit(0);
    }

}
